"""
考试管理模块 - 信号处理
"""
from django.db.models.signals import post_save, post_delete, pre_save
from django.dispatch import receiver
from django.db.models import Count, Avg, Sum
from django.utils import timezone
from datetime import timedelta

from .models import (
    Examination, ExaminationQuestion, ExaminationSession,
    ExaminationAnswer, ExaminationTemplate, ExamStatistics
)
from apps.question_bank.models import QuestionUsageHistory


@receiver(post_save, sender=Examination)
def examination_created(sender, instance, created, **kwargs):
    """考试创建后的信号处理"""
    if created:
        # 创建考试统计对象
        ExamStatistics.objects.get_or_create(examination=instance)

        # 更新题库使用统计
        if instance.question_bank:
            from apps.question_bank.models import QuestionUsageHistory
            QuestionUsageHistory.objects.create(
                question=None,  # 这是题库级别的使用
                user=instance.creator,
                usage_type='exam',
                context={
                    'examination_id': str(instance.id),
                    'examination_title': instance.title,
                    'question_bank_id': str(instance.question_bank.id)
                }
            )


@receiver(post_save, sender=ExaminationQuestion)
def examination_question_created(sender, instance, created, **kwargs):
    """考试题目创建后的信号处理"""
    if created:
        # 更新考试总分
        examination = instance.examination
        total_score = sum(q.effective_score for q in examination.questions.all())
        examination.total_score = total_score
        examination.save(update_fields=['total_score'])

        # 记录题目使用
        QuestionUsageHistory.objects.create(
            question=instance.question,
            user=examination.creator,
            usage_type='exam',
            context={
                'examination_id': str(examination.id),
                'examination_title': examination.title,
                'custom_score': float(instance.custom_score) if instance.custom_score else None
            }
        )


@receiver(post_delete, sender=ExaminationQuestion)
def examination_question_deleted(sender, instance, **kwargs):
    """考试题目删除后的信号处理"""
    examination = instance.examination

    # 重新计算总分
    total_score = sum(q.effective_score for q in examination.questions.all())
    examination.total_score = total_score
    examination.save(update_fields=['total_score'])


@receiver(post_save, sender=ExaminationSession)
def examination_session_created(sender, instance, created, **kwargs):
    """考试会话创建后的信号处理"""
    if created:
        # 更新考试统计信息
        statistics, _ = ExamStatistics.objects.get_or_create(examination=instance.examination)
        statistics.update_statistics()

        # 记录考试使用
        QuestionUsageHistory.objects.create(
            question=None,  # 这是考试级别的使用
            user=instance.user,
            usage_type='exam',
            context={
                'examination_id': str(instance.examination.id),
                'examination_title': instance.examination.title,
                'session_id': str(instance.id)
            }
        )


@receiver(post_save, sender=ExaminationAnswer)
def examination_answer_created(sender, instance, created, **kwargs):
    """考试答案创建后的信号处理"""
    if created:
        # 记录题目使用
        QuestionUsageHistory.objects.create(
            question=instance.exam_question.question,
            user=instance.exam_session.user,
            usage_type='exam',
            context={
                'examination_id': str(instance.exam_session.examination.id),
                'examination_title': instance.exam_session.examination.title,
                'session_id': str(instance.exam_session.id),
                'is_correct': instance.is_correct,
                'time_spent': instance.time_spent
            }
        )

        # 自动评分客观题
        if instance.exam_question.question.type in ['choice', 'multiple_choice', 'true_false']:
            if not instance.score or instance.status == ExaminationAnswer.AnswerStatus.PENDING:
                instance.auto_grade()


@receiver(pre_save, sender=ExaminationAnswer)
def examination_answer_pre_save(sender, instance, **kwargs):
    """考试答案保存前的信号处理"""
    # 确保得分在有效范围内
    if instance.score is not None:
        max_score = instance.exam_question.effective_score
        instance.score = max(0, min(max_score, instance.score))

    # 确保用时为正数
    if instance.time_spent is not None:
        instance.time_spent = max(0, instance.time_spent)


@receiver(post_save, sender=ExaminationSession)
def examination_session_status_changed(sender, instance, created, **kwargs):
    """考试会话状态变更后的信号处理"""
    if not created and hasattr(instance, '_original_status'):
        # 检查状态是否变更
        if instance._original_status != instance.status:
            # 考试完成时计算成绩
            if instance.status == ExaminationSession.SessionStatus.COMPLETED:
                total_score = instance.calculate_score()
                instance.save(update_fields=['total_score', 'passed'])

                # 更新考试统计
                statistics, _ = ExamStatistics.objects.get_or_create(examination=instance.examination)
                statistics.update_statistics()

            # 考试超时时也计算成绩
            elif instance.status == ExaminationSession.SessionStatus.TIMEOUT:
                if instance.started_at:
                    instance.time_spent = int((timezone.now() - instance.started_at).total_seconds())
                total_score = instance.calculate_score()
                instance.save(update_fields=['time_spent', 'total_score', 'passed'])

                # 更新考试统计
                statistics, _ = ExamStatistics.objects.get_or_create(examination=instance.examination)
                statistics.update_statistics()


@receiver(post_save, sender=ExaminationTemplate)
def examination_template_used(sender, instance, created, **kwargs):
    """考试模板使用后的信号处理"""
    if not created:
        # 检查是否是从模板创建考试（通过使用次数判断）
        if hasattr(instance, '_usage_incremented'):
            # 更新题库使用统计
            question_config = instance.question_config or {}
            question_bank_id = question_config.get('question_bank_id')

            if question_bank_id:
                from apps.question_bank.models import QuestionBank
                try:
                    question_bank = QuestionBank.objects.get(id=question_bank_id)
                    QuestionUsageHistory.objects.create(
                        question=None,  # 模板使用
                        user=instance.creator,
                        usage_type='exam',
                        context={
                            'template_id': str(instance.id),
                            'template_name': instance.name,
                            'question_bank_id': question_bank_id
                        }
                    )
                except QuestionBank.DoesNotExist:
                    pass


@receiver(post_save, sender=Examination)
def examination_status_changed(sender, instance, created, **kwargs):
    """考试状态变更后的信号处理"""
    if not created and hasattr(instance, '_original_status'):
        # 检查状态是否变更
        if instance._original_status != instance.status:
            # 考试开始时
            if instance.status == Examination.ExamStatus.ONGOING:
                # 记录考试开始事件
                pass  # 可以添加日志记录

            # 考试结束时
            elif instance.status == Examination.ExamStatus.FINISHED:
                # 自动提交所有进行中的考试会话
                ExaminationSession.objects.filter(
                    examination=instance,
                    status=ExaminationSession.SessionStatus.IN_PROGRESS
                ).update(
                    status=ExaminationSession.SessionStatus.TIMEOUT,
                    finished_at=timezone.now()
                )

                # 更新统计
                statistics, _ = ExamStatistics.objects.get_or_create(examination=instance)
                statistics.update_statistics()

            # 考试发布时
            elif instance.status == Examination.ExamStatus.PUBLISHED:
                # 验证考试配置
                if not instance.questions.exists():
                    # 这里可以添加警告或回滚操作
                    pass


@receiver(post_save, sender=Examination)
def examination_time_check(sender, instance, **kwargs):
    """考试时间检查"""
    now = timezone.now()

    # 检查即将开始的考试（提前30分钟提醒）
    if instance.status == Examination.ExamStatus.PUBLISHED:
        start_time = instance.start_time
        if start_time and now < start_time <= start_time + timedelta(minutes=30):
            # 这里可以发送提醒通知
            pass

    # 自动开始已到时间的考试
    elif instance.status == Examination.ExamStatus.PUBLISHED:
        if instance.start_time and now >= instance.start_time and now <= instance.end_time:
            if not ExaminationSession.objects.filter(
                examination=instance,
                status=ExaminationSession.SessionStatus.IN_PROGRESS
            ).exists():
                # 自动开始考试（如果有考生已加入）
                pass

    # 自动结束已过时间的考试
    elif instance.status == Examination.ExamStatus.ONGOING:
        if instance.end_time and now > instance.end_time:
            instance.status = Examination.ExamStatus.FINISHED
            instance.save(update_fields=['status'])


# 定时任务：检查考试状态
def check_examinations_status():
    """检查所有考试的状态并自动更新"""
    now = timezone.now()

    # 开始已到时间的考试
    examinations_to_start = Examination.objects.filter(
        status=Examination.ExamStatus.PUBLISHED,
        start_time__lte=now,
        end_time__gt=now
    )

    for exam in examinations_to_start:
        exam.status = Examination.ExamStatus.ONGOING
        exam.save(update_fields=['status'])

    # 结束已过时间的考试
    examinations_to_end = Examination.objects.filter(
        status=Examination.ExamStatus.ONGOING,
        end_time__lt=now
    )

    for exam in examinations_to_end:
        exam.status = Examination.ExamStatus.FINISHED
        exam.save(update_fields=['status'])

        # 自动提交所有进行中的考试会话
        ExaminationSession.objects.filter(
            examination=exam,
            status=ExaminationSession.SessionStatus.IN_PROGRESS
        ).update(
            status=ExaminationSession.SessionStatus.TIMEOUT,
            finished_at=now
        )


# 定时任务：清理过期的考试数据
def cleanup_expired_data():
    """清理过期的考试数据"""
    # 删除6个月前的考试会话（仅删除已完成的）
    cutoff_date = timezone.now() - timedelta(days=180)

    ExaminationSession.objects.filter(
        status__in=['completed', 'submitted', 'timeout'],
        finished_at__lt=cutoff_date
    ).delete()


@receiver(pre_save, sender=Examination)
def examination_pre_save(sender, instance, **kwargs):
    """考试保存前的信号处理"""
    # 保存原始状态用于比较
    if instance.pk:
        try:
            old_instance = sender.objects.get(pk=instance.pk)
            instance._original_status = old_instance.status
        except sender.DoesNotExist:
            instance._original_status = None
    else:
        instance._original_status = None

    # 确保考试时长合理
    if instance.duration and instance.duration < 1:
        instance.duration = 60  # 默认1小时
    elif instance.duration and instance.duration > 1440:  # 超过24小时
        instance.duration = 1440

    # 确保时间关系正确
    if instance.start_time and instance.end_time:
        if instance.start_time >= instance.end_time:
            instance.end_time = instance.start_time + timezone.timedelta(hours=1)

        # 根据时长调整结束时间
        expected_end = instance.start_time + timezone.timedelta(minutes=instance.duration)
        if abs((instance.end_time - expected_end).total_seconds()) > 300:  # 5分钟误差
            instance.end_time = expected_end

    # 确保总分合理
    if instance.total_score and instance.total_score <= 0:
        instance.total_score = 100

    # 确保及格分合理
    if instance.pass_score and instance.pass_score < 0:
        instance.pass_score = 60
    elif instance.pass_score and instance.total_score and instance.pass_score > instance.total_score:
        instance.pass_score = instance.total_score * 0.6  # 默认60%及格线


@receiver(pre_save, sender=ExaminationSession)
def examination_session_pre_save(sender, instance, **kwargs):
    """考试会话保存前的信号处理"""
    # 保存原始状态用于比较
    if instance.pk:
        try:
            old_instance = sender.objects.get(pk=instance.pk)
            instance._original_status = old_instance.status
        except sender.DoesNotExist:
            instance._original_status = None
    else:
        instance._original_status = None

    # 记录IP地址
    if not instance.ip_address and hasattr(instance, '_request_ip'):
        instance.ip_address = instance._request_ip

    # 记录用户代理
    if not instance.user_agent and hasattr(instance, '_request_user_agent'):
        instance.user_agent = instance._request_user_agent[:500]